package club.janna.hello.parser;

//import club.janna.hello.factory.DeviceFactory;
//import club.janna.hello.model.Inverter;

import club.janna.hello.dao.MemoryChannelDao;
import club.janna.hello.frame.Aux;
import club.janna.hello.frame.DataUnit;
import club.janna.hello.frame.GDW376D1;
import club.janna.hello.frame.GDW376D1UserData;
import club.janna.hello.handle.GDW376D1Handle;
import club.janna.hello.model.ChannelModel;
import club.janna.hello.parser.constants.GDW376D1Statute;
import club.janna.hello.parser.constants.IEC104Statute;
import club.janna.hello.util.DataConvertor;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//import club.janna.hello.util.CommonUtil;
//import club.janna.hello.util.TemplateUtilTest;

/**
 * Created by guopanbo on 17/12/28
 */
public class GDW376D1Parser implements Runnable {

    private byte[] data;
    private ChannelHandlerContext ctx;

    public GDW376D1Parser(byte[] data, ChannelHandlerContext ctx) {
        this.data = data;
        this.ctx = ctx;
    }

    /**
     * 解析规约
     * @param source 10进制数字数组
     * @return
     */
    private int parse(int[] source) {
        short offset = 0;

        /**
         * 判断起始和结束是否正确
         */
        if(source[0] != GDW376D1Statute.START || source[5] != GDW376D1Statute.START || source[source.length - 1] != GDW376D1Statute.END)
            throw new RuntimeException("frame start or end invalid");
        /**
         * 判断帧校验和是否正确
         */
        if(source[source.length - 2] != GDW376D1Statute.CRC(source))
            throw new RuntimeException("crc invalid");

        /**
         * 判断帧长度是否正确
         */
        if((DataConvertor.int2Byte2IntFLAH(source[1], source[2]) >> 2) + 8 != source.length)
            throw new RuntimeException("frame length[%d] invalid");

        GDW376D1 f = new GDW376D1();

        /**
         * 起始
         */
        f.setStart((byte)source[offset ++]);
        /**
         * 长度
         */
        f.setLength(DataConvertor.int2Byte2IntFLAH(source[offset ++], source[offset ++]) >> 2);
        /**
         * 长度
         */
        f.setLength1(DataConvertor.int2Byte2IntFLAH(source[offset ++], source[offset ++]) >> 2);
        /**
         * 起始
         */
        f.setStart1((byte)source[offset ++]);
        /**
         * 控制域
         */
        f.setCtl((short)source[offset ++]);
        /**
         * 行政区划码
         */
        f.setAreaCode(DataConvertor.int2Byte2IntFLAH(source[offset ++], source[offset ++]));
        /**
         * 终端地址
         */
        f.setAddress(DataConvertor.int2Byte2IntFLAH(source[offset ++], source[offset ++]));
        /**
         * 地址标志
         */
        f.setAddressMark((short)source[offset ++]);

        //保存通道
        ChannelModel channel = new ChannelModel();
        channel.setId(String.valueOf(f.getAreaCode()) + String.valueOf(f.getAddress()));
        channel.setChannel(ctx.channel());
        MemoryChannelDao.getInstance().doCreate(channel);


        /**
         * 应用层功能码AFN
         */
        f.setAfn((short)source[offset ++]);
        /**
         * 帧序列域SEQ
         */
        f.setSeq((short)source[offset ++]);

        /**
         * 数据域
         */
        int dataLength = f.getLength() - 8;
        int[] fData = new int[dataLength];
        System.arraycopy(source, offset, fData, 0, dataLength);
        f.setData(fData);

        offset += dataLength;

        //List<DataUnit> dataUnits = null;
        //int dataLength = f.getLength() - 8;
        //boolean haveAux = false;
        //if(dataLength >= 0) {
        //    //如果数据域长度为4，则说明只存在一个数据单元标识，没有数据单元和aux
        //    if (dataLength == 4) {
        //        DataUnit dataUnit = new DataUnit();
        //        dataUnit.setDa1(Integer.toBinaryString(source[offset ++]));
        //        dataUnit.setDa2((short)source[offset ++]);
        //        dataUnit.setDt1(Integer.toBinaryString(source[offset ++]));
        //        dataUnit.setDt2((short)source[offset ++]);
        //        if(dataUnits == null)
        //            dataUnits = new ArrayList<>();
        //        dataUnits.add(dataUnit);
        //    } else {
        //        //大于4，则说明可能有数据单元和aux
        //        //是否存在附加信息域
        //        haveAux = (dataLength & 0b11) != 0 && (dataLength & 0b111) != 0;
        //        //for (int i = 0; i < (dataLength / 4); i++) {
        //        //
        //        //}
        //    }
        //}
        //f.setDataUnits(dataUnits);

        /**
         * 如果存在aux
         */
        //if(haveAux)
        //    f.setAux(new Aux());

        /**
         * 校验位
         */
        f.setCrc((short)source[offset ++]);
        /**
         * 结束
         */
        f.setEnd((byte)source[offset ++]);

        new GDW376D1Handle().handle(f);
        return 0;
    }

    @Override
    public void run() {
        if(data == null || data.length == 0)
            throw new RuntimeException("data is null");
        int[] decArray = DataConvertor.HexByteArray2DecArray(data);
        System.out.println("服务器接收到的数据：" + DataConvertor.Byte2String(data));
        System.out.println("线程：" + Thread.currentThread().getName());
        parse(decArray);
    }
}
